package svc

import (
	"context"
	"dfx_cmdb/cmdb-blacklist-rpc/internal/config"
	cmdbblacklist "dfx_cmdb/models/cmdb-blacklist"
	"fmt"
	"strings"

	toolsdatabase "gitee.com/daofeixian/dfx_golang_toolset/databases"
	toolsnosql "gitee.com/daofeixian/dfx_golang_toolset/nosqls"
	"github.com/it512/xxl-job-exec"
	"github.com/robfig/cron/v3"
	"github.com/zeromicro/go-zero/core/logc"
	"gorm.io/gorm"
)

const (
	HaproxyBlackList   = "haproxy_blacklist"
	OpenrestyBlackList = "openresty_blacklist"
	EBPFBlackList      = "ebpf_blacklist"
)

type ServiceContext struct {
	Config config.Config
	Cron   *cron.Cron
	PDB    *gorm.DB
	CDB    *gorm.DB
	RC     toolsnosql.RedisClient
	// BlackListStatusMap 用于对外快速返回各黑名单开关状态（true=已启用，false=未启用）
	BlackListStatusMap map[string]bool
	Exec               *xxl.Executor
}

func NewServiceContext(c config.Config) *ServiceContext {
	cxt := context.Background()

	cronInstance := cron.New()
	cronInstance.Start() // 在这里启动一次

	// 规范化 URI，避免出现双斜杠导致注册/访问路径不一致
	normalizedURI := strings.TrimPrefix(c.XxlJobAdmin.XxlJobExecutor.Uri, "/")
	executorUrl := fmt.Sprintf("http://%s:%d/%s", c.XxlJobAdmin.XxlJobExecutor.LoopbackAddress, c.XxlJobAdmin.XxlJobExecutor.Port, normalizedURI)

	exec := xxl.NewExecutor(
		xxl.ServerAddr(c.XxlJobAdmin.URL),
		xxl.AccessToken(c.XxlJobAdmin.Token),
		xxl.RegistryKey(c.XxlJobAdmin.RegisterKey),
		xxl.ExecutorURL(executorUrl),
	)

	pdb, cdb, rc := initDBClient(cxt, c)
	autoMigrate(cxt, pdb, c)

	s := &ServiceContext{
		Config: c,
		Cron:   cronInstance,
		PDB:    pdb,
		CDB:    cdb,
		RC:     rc,
		Exec:   exec,
	}

	return s
}

// initDBClient 初始化数据库和 Redis 客户端
// 参数:
//   - cxt: 上下文对象，用于控制请求生命周期
//   - c: 配置对象，包含数据库和 Redis 的配置信息
//
// 返回值:
//   - pdb: PostgreSQL 数据库连接客户端 (*gorm.DB)
//   - cdb: ClickHouse 数据库连接客户端 (*gorm.DB)
//   - rc: Redis 客户端 (toolsnosql.RedisClient)
func initDBClient(cxt context.Context, c config.Config) (pdb *gorm.DB, cdb *gorm.DB, rc toolsnosql.RedisClient) {
	// 遍历数据库配置，初始化 PostgreSQL 和 ClickHouse 连接
	for _, v := range c.DatabasesConfig {
		if v.Type == "postgresql" && v.Name == "cmdb" {
			pdb = toolsdatabase.InitDBter(&v).InitDB()
			logc.Infof(cxt, "%s postgresql 链接成功", v.Host)
		}
		if v.Type == "clickhouse" && v.Name == "otel" {
			cdb = toolsdatabase.InitDBter(&v).InitDB()
			logc.Infof(cxt, "%s clickhouse 连接成功", v.Host)
		}
	}
	// 遍历 Redis 配置，初始化指定名称的 Redis 客户端
	for _, v := range c.RedisConfig {
		if v.Name == "cmdb" {
			rc = toolsnosql.InitNosqlter(&v).InitRedis()
		}
	}
	return
}

// autoMigrate 自动迁移数据库表结构
// 参数:
//   - cxt: 上下文对象
//   - pdb: PostgreSQL 数据库客户端
//   - c: 配置对象，判断是否开启自动迁移功能
func autoMigrate(cxt context.Context, pdb *gorm.DB, c config.Config) {
	// 如果启用了自动迁移，则执行模型的自动迁移操作
	if c.DBAUTO {
		err := pdb.AutoMigrate(&cmdbblacklist.BlacklistIgnoreRule{})
		if err != nil {
			logc.Error(cxt, "数据库迁移失败")
		}
	}
}
